/*
 * Copyright (c) 2025 Industrial Software Feature Database
 */
package com.comac.ins.isfd.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.comac.ins.common.core.exception.base.BaseException;
import com.comac.ins.common.core.utils.MapstructUtils;
import com.comac.ins.common.core.utils.StringUtils;
import com.comac.ins.common.mybatis.core.page.PageQuery;
import com.comac.ins.common.mybatis.core.page.TableDataInfo;
import com.comac.ins.isfd.domain.IsfdSceneMap;
import com.comac.ins.isfd.domain.bo.IsfdSceneMapBo;
import com.comac.ins.isfd.domain.bo.IsfdSceneMapStepBo;
import com.comac.ins.isfd.domain.bo.query.IsfdSceneMapQueryBo;
import com.comac.ins.isfd.domain.vo.*;
import com.comac.ins.isfd.domain.vo.blood.BloodRelationshipOuterV2Vo;
import com.comac.ins.isfd.domain.vo.blood.BloodRelationshipV2Vo;
import com.comac.ins.isfd.mapper.IsfdBusinessScenariosMapper;
import com.comac.ins.isfd.mapper.IsfdSceneMapMapper;
import com.comac.ins.isfd.service.IIsfdDatabaseTypeManagementService;
import com.comac.ins.isfd.service.IIsfdSceneMapService;
import com.comac.ins.isfd.service.IIsfdSceneMapStepService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 系统地图Service业务层处理
 *
 * @author hxloongs
 * @date 2025-03-03
 */
@RequiredArgsConstructor
@Service
public class IsfdSceneMapServiceImpl implements IIsfdSceneMapService {

    @Autowired
    private IsfdSceneMapMapper baseMapper;

    @Autowired
    private IIsfdSceneMapStepService iIsfdSceneMapStepService;

    @Autowired
    private IIsfdDatabaseTypeManagementService iIsfdDatabaseTypeManagementService;

//    @Autowired
//    private IsfdDatabaseTypeManagementMapper isfdDatabaseTypeManagementMapper;

    @Autowired
    private IsfdBusinessScenariosMapper isfdBusinessScenariosMapper;

    @Override
    public IsfdSceneMapVo detail(Long id, Boolean needStatistics) {
        // 查询地图
        IsfdSceneMapVo isfdSceneMapVo = baseMapper.selectVoById(id);
        if (isfdSceneMapVo == null) {
            throw new BaseException("未查到相关系统地图数据");
        }
        IsfdBusinessScenariosVo sceneVo = isfdBusinessScenariosMapper.selectVoById(isfdSceneMapVo.getSceneId());
        IsfdBusinessScenariosVo systemVo = isfdBusinessScenariosMapper.selectVoById(isfdSceneMapVo.getSystemId());
        isfdSceneMapVo.setSceneName(sceneVo.getName());
        isfdSceneMapVo.setSystemName(systemVo.getName());

        // 查询地图步骤
        List<IsfdSceneMapStepVo> isfdSceneMapStepList = iIsfdSceneMapStepService.queryListByMapId(id, needStatistics);
        isfdSceneMapVo.setIsfdSceneMapStepList(isfdSceneMapStepList);
        if (!CollectionUtils.isEmpty(isfdSceneMapStepList)) {
            int count = 0;
            Set<Long> databaseTypeIdSet = new HashSet<>();
            for (IsfdSceneMapStepVo mapStepVo : isfdSceneMapStepList) {
                List<IsfdSceneMapStepModelRefVo> modelRefList = mapStepVo.getModelRefList();
                int size = modelRefList.size();
                count = count + size;
                for (IsfdSceneMapStepModelRefVo mapStepModelRefVo : modelRefList) {
                    Long databaseTypeId = mapStepModelRefVo.getDatabaseTypeId();
                    databaseTypeIdSet.add(databaseTypeId);
                }
            }
            isfdSceneMapVo.setModelCount(count);
            // 查询要素库类型数据
            isfdSceneMapVo.setIsfdDatabaseTypeManagementTree(iIsfdDatabaseTypeManagementService.queryTreeByIds(databaseTypeIdSet));
        }

        return isfdSceneMapVo;
    }

    @Override
    public TableDataInfo<IsfdSceneMapPageVo> queryPageList(IsfdSceneMapQueryBo queryBo) {
        PageQuery pageQuery = new PageQuery();
        pageQuery.setPageNum(queryBo.getPageNum());
        pageQuery.setPageSize(queryBo.getPageSize());
        Page<IsfdSceneMapPageVo> result = baseMapper.queryPageList(pageQuery.build(), queryBo.getSceneName(), queryBo.getSystemName());
        return TableDataInfo.build(result);
    }

    @Override
    public List<IsfdSceneMapVo> queryList(IsfdSceneMapBo bo) {
        LambdaQueryWrapper<IsfdSceneMap> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }


    private LambdaQueryWrapper<IsfdSceneMap> buildQueryWrapper(IsfdSceneMapBo bo) {
        LambdaQueryWrapper<IsfdSceneMap> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getSceneId() != null, IsfdSceneMap::getSceneId, bo.getSceneId());
        lqw.eq(bo.getSystemId() != null, IsfdSceneMap::getSystemId, bo.getSystemId());
        lqw.eq(StringUtils.isNotBlank(bo.getDescription()), IsfdSceneMap::getDescription, bo.getDescription());
        return lqw;
    }

    @Override
    @Transactional
    public Boolean save(IsfdSceneMapBo bo) {
        // 0.做下校验
        checkParams(bo);
        IsfdSceneMap map = MapstructUtils.convert(bo, IsfdSceneMap.class);
        Long mapId = map.getId();
        Long newMapId = null;
        // 1.处理map数据
        if (mapId == null) {
            baseMapper.insert(map);
            newMapId = map.getId();
        } else {
            baseMapper.updateById(map);
        }
        // 2.处理地图步骤数据
        iIsfdSceneMapStepService.save(mapId, bo.getIsfdSceneMapStepList(), newMapId);
        return Boolean.TRUE;
    }


    @Override
    @Transactional
    public Boolean deleteWithValidById(Long id) {
        baseMapper.deleteById(id);
        iIsfdSceneMapStepService.deleteWithByMapId(id);
        return Boolean.TRUE;
    }

    @Override
    public void checkByConditionsForDelete(Long sceneId, Long databaseTypeId, Long systemId, Long parentModelId) {
        if (sceneId != null) {
            IsfdSceneMapBo bo = new IsfdSceneMapBo();
            bo.setSceneId(sceneId);
            List<IsfdSceneMapVo> mapVoList = this.queryList(bo);
            if (!CollectionUtils.isEmpty(mapVoList)) {
                throw new BaseException("当前业务场景关联了 系统地图，请删除相关系统地图后，再删除该业务场景！");
            }
        }
        if (databaseTypeId != null) {
            IsfdSceneMapBo bo = new IsfdSceneMapBo();
            bo.setSystemId(databaseTypeId);
            List<IsfdSceneMapVo> mapVoList = this.queryList(bo);
            if (!CollectionUtils.isEmpty(mapVoList)) {
                throw new BaseException("当前业务系统关联了 系统地图，请删除相关系统地图后，再删除该业务系统！");
            }
        }
        if (databaseTypeId != null) {
            List<IsfdSceneMapStepVo> mapStepVoList = iIsfdSceneMapStepService.findMapStepVoListByDatabaseIdAndModelId(databaseTypeId, null);
            if (!CollectionUtils.isEmpty(mapStepVoList)) {
                List<Long> mapIds = mapStepVoList.stream().map(IsfdSceneMapStepVo::getMapId).toList();
                List<IsfdSceneMapVo> mapVoList = baseMapper.selectVoList(new LambdaQueryWrapper<IsfdSceneMap>().in(IsfdSceneMap::getId, mapIds));
                if (!CollectionUtils.isEmpty(mapVoList)) {
                    throw new BaseException("当前数据库类型关联了 系统地图，请删除相关系统地图后，再删除该要素库类型！");
                }
            }
        }
        if (parentModelId != null) {
            List<IsfdSceneMapStepVo> mapStepVoList = iIsfdSceneMapStepService.findMapStepVoListByDatabaseIdAndModelId(null, parentModelId);
            if (!CollectionUtils.isEmpty(mapStepVoList)) {
                List<Long> mapIds = mapStepVoList.stream().map(IsfdSceneMapStepVo::getMapId).toList();
                List<IsfdSceneMapVo> mapVoList = baseMapper.selectVoList(new LambdaQueryWrapper<IsfdSceneMap>().in(IsfdSceneMap::getId, mapIds));
                if (!CollectionUtils.isEmpty(mapVoList)) {
                    throw new BaseException("当前模型关联了 系统地图，请删除相关系统地图后，再删除该模型！");
                }
            }
        }
    }

    @Override
    public BloodRelationshipV2Vo relationship(Long sceneMapStepModelRefId) {
        BloodRelationshipV2Vo bloodRelationshipV2Vo = new BloodRelationshipV2Vo();
        IsfdSceneMapStepModelRefVo mapStepModelRefVo = iIsfdSceneMapStepService.querySceneMapStepModelRefVo(sceneMapStepModelRefId);
        Long mapStepId = mapStepModelRefVo.getMapStepId();
        IsfdSceneMapStepVo mapStepVo = iIsfdSceneMapStepService.queryById(mapStepId);
        if (mapStepVo == null) {
            throw new BaseException("关联关系不存在，请确认后重试！");
        }
        Long mapId = mapStepVo.getMapId();
        IsfdSceneMapVo mapVo = baseMapper.selectVoById(mapId);
        if (mapVo == null) {
            throw new BaseException("系统地图不存在，请确认后重试！");
        }
        Long sceneId = mapVo.getSceneId();
        Long systemId = mapVo.getSystemId();
        IsfdBusinessScenariosVo sceneVo = isfdBusinessScenariosMapper.selectVoById(sceneId);
        IsfdBusinessScenariosVo systemVo = isfdBusinessScenariosMapper.selectVoById(systemId);

        Long databaseTypeId = mapStepModelRefVo.getDatabaseTypeId();
        IsfdDatabaseTypeManagementVo databaseTypeManagementVo = iIsfdDatabaseTypeManagementService.queryById(databaseTypeId);
        Long modelId = mapStepModelRefVo.getModelId();
        List<BloodRelationshipOuterV2Vo> outerList = iIsfdSceneMapStepService.relationship(sceneId, systemId, databaseTypeId, modelId);

        bloodRelationshipV2Vo.setLevel(1);
        bloodRelationshipV2Vo.setMapId(mapId);
        bloodRelationshipV2Vo.setSceneId(sceneId);
        bloodRelationshipV2Vo.setSceneName(sceneVo.getName());
        bloodRelationshipV2Vo.setSystemId(systemId);
        bloodRelationshipV2Vo.setSystemName(systemVo.getName());
        bloodRelationshipV2Vo.setDatabaseTypeId(databaseTypeId);
        bloodRelationshipV2Vo.setDatabaseName(databaseTypeManagementVo.getDatabaseName());
        bloodRelationshipV2Vo.setChildren(outerList);
        return bloodRelationshipV2Vo;
    }


    /**
     * 参数校验
     */
    private void checkParams(IsfdSceneMapBo bo) {
        if (bo.getSceneId() == null || bo.getSystemId() == null) {
            throw new BaseException("必填参数为空，请确认后重试！");
        }
        if (CollectionUtils.isEmpty(bo.getIsfdSceneMapStepList())) {
            throw new BaseException("未选择模型，请确认后重试！");
        }
        List<IsfdSceneMapStepBo> isfdSceneMapStepList = bo.getIsfdSceneMapStepList();
        for (IsfdSceneMapStepBo sceneMapStepBo : isfdSceneMapStepList) {
            List<IsfdSceneMapStepBo.ChoseDataBaseAndModel> modelRefList = sceneMapStepBo.getModelRefList();
            Set<String> tempSet = new HashSet<>();
            for (IsfdSceneMapStepBo.ChoseDataBaseAndModel choseDataBaseAndModel : modelRefList) {
                Long databaseTypeId = choseDataBaseAndModel.getDatabaseTypeId();
                Long modelId = choseDataBaseAndModel.getModelId();
                String key = databaseTypeId + "_" + modelId;
                if (tempSet.contains(key)) {
                    throw new BaseException("在步骤：" + sceneMapStepBo.getStepRank() + "中存在相同的模型，同一步骤不能有相同模型！");
                }
                tempSet.add(key);
            }
        }
    }
}
